﻿ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace GraphicsLib
{   
    /// <summary>
    /// Provides methods for drawing 2D primitives
    /// </summary>
    public class Graphics2D
    {
        private SpriteBatch mySpriteBatch;
        private Texture2D myBaseTexture;
        private Random myRand;

        public enum eBorderType
        {
            Internal,
            External
        }

        public enum eFillType
        {
            Outline,
            Filled
        }

        public Graphics2D(SpriteBatch _spriteBatch, Texture2D _baseTexture)
        {
            mySpriteBatch = _spriteBatch;
            myBaseTexture = _baseTexture;
            myRand = new Random();
        }

        private Rectangle GetRandomRectangle(int _width, int _height, int _division)
        {
            int width = _width / _division;
            int height = _height / _division;
            int x = myRand.Next(_width - width);
            int y = myRand.Next(_height - height);

            return new Rectangle(x, y, width, height);
        }

        #region Lines

        public void DrawLineBetweenPoints
            (Vector2 _pointA, Vector2 _pointB, Color _color, int _width)
        {
            DrawLineBetweenPoints(_pointA, _pointB, myBaseTexture, _color, _width);
        }
        
        private void DrawLineBetweenPoints(
            Vector2 _pointA, Vector2 _pointB, Texture2D _texture, Color _color, int _width)
        {
            Vector2 direction = _pointA - _pointB;
            float angle = (float)Math.Atan2((double)direction.Y, (double)direction.X);
            angle += MathHelper.PiOver2; // hax for spritebatch being weird
            float distance = direction.Length();

            mySpriteBatch.Draw(
                _texture, // texture
                _pointA, // position
                null, // source rectangle
                _color,
                angle,
                new Vector2(0), // rotation origin
                new Vector2(_width, distance), // scaling - seems like this only works for single pixel textures
                SpriteEffects.None,
                0);
        }

        public void DrawLaserLineBetweenPoints(
            Vector2 _pointA, Vector2 _pointB, Texture2D _texture, Color _color, int _width)
        {
            Vector2 diff = _pointA - _pointB;
            float len = diff.Length() / (_texture.Width/8);

            for (int i = 0; i < len; i++)
            {
                // todo: work out scaling, so that _width actually gives us the bloody width of the line
                mySpriteBatch.Draw(_texture, _pointA, GetRandomRectangle(_texture.Width, _texture.Height, 16), _color);
                _pointA.X -= diff.X / len;
                _pointA.Y -= diff.Y / len;
            }
        }

        #endregion Lines        

        #region Rectangles

        public void DrawRectangle(Vector2 _position, int _width, int _height, Color _color)
        {
            DrawRectangle(new Rectangle((int)_position.X, (int)_position.Y, _width, _height), _color);
        }

        public void DrawRectangle(int _x, int _y, int _width, int _height, Color _color)
        {
            DrawRectangle(new Rectangle(_x, _y, _width, _height), _color);
        }

        public void DrawRectangle(Rectangle _rectangle, Color _color)
        {
            mySpriteBatch.Draw(
                myBaseTexture,
                _rectangle,
                _color);
        }

        public void DrawBorderedRectangle(
            int _x, 
            int _y, 
            int _width, 
            int _height, 
            int _borderWidth, 
            Color _mainColor, 
            Color _borderColor, 
            eBorderType _borderType)
        {
            DrawBorderedRectangle(
                new Rectangle(_x, _y, _width, _height), _borderWidth, _mainColor, _borderColor, _borderType);
        }

        public void DrawBorderedRectangle(
            Rectangle _rectangle, int _borderWidth, Color _mainColor, Color _borderColor, eBorderType _borderType)
        {
            if(_borderType == eBorderType.Internal)
            {
                DrawRectangleInternalBorder(_rectangle, _borderWidth, _mainColor, _borderColor);
            }
            else if (_borderType == eBorderType.External)
            {
                DrawRectangleExternalBorder(_rectangle, _borderWidth, _mainColor, _borderColor);
            }
        }

        private void DrawRectangleExternalBorder(
            Rectangle _rectangle, int _borderWidth, Color _mainColor, Color _borderColor)
        {
            DrawRectangle(
                new Rectangle(
                    _rectangle.X - _borderWidth,
                    _rectangle.Y - _borderWidth,
                    _rectangle.Width + (_borderWidth * 2),
                    _rectangle.Height + (_borderWidth * 2)),
                _borderColor);
            DrawRectangle(_rectangle, _mainColor);
        }

        public void DrawRectangleInternalBorder(
            Rectangle _rectangle, int _borderWidth, Color _mainColor, Color _borderColor)
        {
            DrawRectangle(_rectangle, _borderColor);
            DrawRectangle(
                new Rectangle(
                    _rectangle.X + _borderWidth,
                    _rectangle.Y + _borderWidth,
                    _rectangle.Width - (_borderWidth * 2),
                    _rectangle.Height - (_borderWidth * 2)),
                _mainColor);
        }

        #endregion Rectangles        

        #region Outline Shapes

        public void DrawRectangleOutline(int _x, int _y, int _width, int _height, int _lineWidth, Color _color)
        {
            DrawRectangleOutline(new Rectangle(_x, _y, _width, _height), _lineWidth, _color);
        }

        public void DrawRectangleOutline(Rectangle _rectangle, int _lineWidth, Color _color)
        {
            DrawLineBetweenPoints(
                new Vector2(_rectangle.Left, _rectangle.Bottom),
                new Vector2(_rectangle.Left, _rectangle.Top - _lineWidth),
                _color,
                _lineWidth);
            DrawLineBetweenPoints(
                new Vector2(_rectangle.Left, _rectangle.Top),
                new Vector2(_rectangle.Right + _lineWidth, _rectangle.Top),
                _color, 
                _lineWidth);
            DrawLineBetweenPoints(
                new Vector2(_rectangle.Right, _rectangle.Top), 
                new Vector2(_rectangle.Right, _rectangle.Bottom + _lineWidth), 
                _color, 
                _lineWidth);
            DrawLineBetweenPoints(
                new Vector2(_rectangle.Right, _rectangle.Bottom), 
                new Vector2(_rectangle.Left - _lineWidth, _rectangle.Bottom),
                _color, 
                _lineWidth);
        }

        #endregion Outline Shapes
    }
}
